﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VntNet.PowerSchemeSwitcher.Properties;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Microsoft.Win32;

namespace VntNet.PowerSchemeSwitcher
{
    public partial class MainForm : Form
    {
        private ToolStripMenuItem SelectedMenuItem;
        Dictionary< Guid,PowerPlanInfo> PowerPlans;
        PowerSettingNotificationMsgFilter pwrNotMsgFilter;
        ToolStripMenuItem menuExitItem;
        PowerLineHelper powerLineHelper;
        string currentSchemeName;
        string currentLineName;

        public MainForm()
        {
            InitializeComponent();
            notifyIcon.Icon = Resources.TypicalPowerIcon;
            this.Icon = Resources.TypicalPowerIcon;
            SelectedMenuItem = null;
            powerLineHelper = new PowerLineHelper();
            currentLineName = PowerLineHelper.GetCurrentSystemPowerStatus().ToString();
            powerLineHelper.OnPowerLineStatusChanged += new Action<PowerLineHelper.PowerLineStatus>(powerLineHelper_OnPowerLineStatusChanged);
        }

        private void UpdateToolTip()
        {
            notifyIcon.Text = String.Format("{0}{1}{2}",currentLineName, Environment.NewLine, currentSchemeName);
        }

        void powerLineHelper_OnPowerLineStatusChanged(PowerLineHelper.PowerLineStatus obj)
        {
            currentLineName = PowerLineHelper.GetCurrentSystemPowerStatus().ToString();
        }


        // I have to override win proc as IMessageFilter was not filtering power messages
        protected override void WndProc(ref Message m)
        {
            if (pwrNotMsgFilter != null)
            {
                if (!pwrNotMsgFilter.PreFilterMessage(ref m))
                    base.WndProc(ref m);
            }
            base.WndProc(ref m);
        }

        #region Form
        private void Form1_Load(object sender, EventArgs e)
        {
            AddPowerPlansAsMenuItems();
            AddExitMenuItem();
            AttachPowerSettingNotificationMsgFilter();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            //hide immediatly
            Hide();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
                Hide();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            DetachPowerSettingNotificationMsgFilter();
        }

        #endregion

        private void ShowAbout()
        {
            AbautDialog dlg = new AbautDialog();
            dlg.ShowDialog();
        }
        private void notifyIcon_DoubleClick(object sender, EventArgs e)
        {
            ShowAbout();
            //WindowState = FormWindowState.Normal;
        }

        private void notifyIcon_Click(object sender, EventArgs e)
        {
            //I need to do this as there is no specific events that inform
            //about scheme deletion
            UpdatePowerPlansMenuItems();
        }

        #region PowerSettingNotification
        private void AttachPowerSettingNotificationMsgFilter()
        {
            pwrNotMsgFilter = new PowerSettingNotificationMsgFilter(this);
            pwrNotMsgFilter.OnPowerSchemeChanged += new Action<PowerSettingNotificationMsgFilter.PowerSavingLevelEnum>(pwrNotMsgFilter_OnPowerSchemeChanged);
        }

        private void DetachPowerSettingNotificationMsgFilter()
        {
            pwrNotMsgFilter.Destroy();
        }

        void pwrNotMsgFilter_OnPowerSchemeChanged(PowerSettingNotificationMsgFilter.PowerSavingLevelEnum powerSavingLevel)
        {
            UpdatePowerPlansMenuItems();
            Guid activeSchemeGuid = PowerSchemeHelper.GetPowerActiveScheme();
            foreach (var p in PowerPlans)
            {
                if (p.Key == activeSchemeGuid)
                {
                    CheckMenuItem((ToolStripMenuItem)p.Value.Tag);
                    currentSchemeName = p.Value.FriendlyName;
                    UpdateToolTip();
                }
            }
            switch (powerSavingLevel)
            {
                case PowerSettingNotificationMsgFilter.PowerSavingLevelEnum.Max:
                    notifyIcon.Icon = Resources.MaxPowerIcon;
                    break;
                case PowerSettingNotificationMsgFilter.PowerSavingLevelEnum.Min:
                    notifyIcon.Icon = Resources.MaxSavingIcon;
                    break;
                case PowerSettingNotificationMsgFilter.PowerSavingLevelEnum.Typical:
                    notifyIcon.Icon = Resources.TypicalPowerIcon;
                    break;
                default:
                    notifyIcon.Icon = Resources.TypicalPowerIcon;
                    break;
            }
        }
        #endregion

        #region Menu Items
        void menuItem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
            PowerPlanInfo powerPlanInfo = menuItem.Tag as PowerPlanInfo;
            powerPlanInfo.Set();
        }

        void menuExitItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void AddExitMenuItem()
        {
            menuExitItem = new ToolStripMenuItem("Exit");
            menuExitItem.Click += new EventHandler(menuExitItem_Click);
            this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { menuExitItem });
        }

        private void UpdatePowerPlansMenuItems()
        {
            var CurrentPlanList = PowerSchemeHelper.GetAllPowerSchemas();
            //search for new palns
            foreach (var i in CurrentPlanList)
            {
                //new power scheme?
                if (!PowerPlans.ContainsKey(i.Key))
                {
                    AddMenuItem(i.Value);
                    PowerPlans.Add(i.Key, i.Value);
                }
                else
                {
                    //see if we chacnged the name
                    var tempPlan = PowerPlans[i.Key];
                    if (i.Value.FriendlyName != tempPlan.FriendlyName)
                    {
                        ((ToolStripMenuItem)tempPlan.Tag).Text = i.Value.FriendlyName;
                    }
                }
            }
            //search for deleted plans
            for(int i=PowerPlans.Count-1;i>=0;i--)
            {
                var p = PowerPlans.ElementAt(i);
                //detete old ones
                if (!CurrentPlanList.ContainsKey(p.Key))
                {
                    RemoveMenuItem(p.Value);
                    PowerPlans.Remove(p.Key);
                }
            }
        }

        private void AddPowerPlansAsMenuItems()
        {
            PowerPlans = PowerSchemeHelper.GetAllPowerSchemas();
            foreach (var p in PowerPlans)
            {
                AddMenuItem(p.Value);
            }
            //force a refresh
            PowerSchemeHelper.SetPowerScheme(PowerSchemeHelper.GetPowerActiveScheme());
        }

        private void RemoveMenuItem(PowerPlanInfo powerPlanInfo)
        {
            ToolStripMenuItem menuItem = (ToolStripMenuItem)powerPlanInfo.Tag;
            this.contextMenuStrip.Items.Remove(menuItem);
        }

        private void AddMenuItem(PowerPlanInfo powerPlanInfo)
        {
            //TODO: add items in aphabetical order
            ToolStripMenuItem menuItem = new ToolStripMenuItem(powerPlanInfo.FriendlyName);
            menuItem.Tag = powerPlanInfo;
            menuItem.Click += new EventHandler(menuItem_Click);
            powerPlanInfo.Tag = menuItem;
            if (menuExitItem == null)
                this.contextMenuStrip.Items.Add( menuItem);
            else
            {
                //we want exit to be the last item
                this.contextMenuStrip.Items.Insert(contextMenuStrip.Items.Count - 1, menuItem);
            }
        }

        private void CheckMenuItem(ToolStripMenuItem menuItem)
        {
            //unchek previus one
            if (SelectedMenuItem != null)
                SelectedMenuItem.Checked = false;
            //remember wich is the current selected item
            SelectedMenuItem = menuItem;
            //applay the change
            menuItem.Checked = true;
        }     
        #endregion

        
    }
}
